package com.cn.lp.openapi.processor;

import com.cn.lp.openapi.base.ParameterExpander;
import com.cn.lp.openapi.param.RequestParam;
import feign.MethodMetadata;
import feign.Param;
import feign.Util;
import org.springframework.cloud.openfeign.annotation.RequestParamParameterProcessor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * GetRequestParam注解处理器
 * 通过Expander触发RequestParam的initMap方法，把对象属性注入Map中，然后通过queryMapIndex触发Map转param
 */
public class GetRequestParamParameterProcessor extends RequestParamParameterProcessor {

    private boolean encode = false;

    private Charset charset = Util.UTF_8;

    public static GetRequestParamParameterProcessor build(boolean encode, Charset charset) {
        GetRequestParamParameterProcessor getRequestParamParameterProcessor = new GetRequestParamParameterProcessor();
        getRequestParamParameterProcessor.encode = encode;
        getRequestParamParameterProcessor.charset = charset;
        return getRequestParamParameterProcessor;
    }

    @Override
    public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
        int parameterIndex = context.getParameterIndex();
        Class<?> parameterType = method.getParameterTypes()[parameterIndex];
        MethodMetadata data = context.getMethodMetadata();
        if (RequestParam.class.isAssignableFrom(parameterType)) {
            // 留有参数，触发Expander
            context.setParameterName("s");
            Map<Integer, Param.Expander> indexToExpander= data.indexToExpander();
            indexToExpander.put(parameterIndex, ParameterExpander.build(encode, charset));
            data.indexToEncoded().put(parameterIndex, Boolean.FALSE);
            MethodMetadata metadata = context.getMethodMetadata();
            if (metadata.queryMapIndex() == null) {
                metadata.queryMapIndex(parameterIndex);
                // 可配置
                metadata.queryMapEncoded(true);
            }
            return true;
        }
        return super.processArgument(context, annotation, method);
    }

}
